
#include <stdio.h>
#include "IBroadphase.h"
#include "member_BBody.h"

using namespace BWE;

IBroadphase::IBroadphase()
{
	_overlapPairs.reserve(100);
}
IBroadphase::~IBroadphase()
{

}

void IBroadphase::createProxy(BBody* body)
{
	const BSpace& space = body->space();
	BodyProxy* bodyProxy = new BodyProxy(body, space);
	bodyProxy->leaf = _spaceTree.insert(space, bodyProxy);
	body_member(body)->bodyProxy = bodyProxy;
	_spaceTree.collide(_spaceTree.root(), space, _spaceNodes);
	for (int i = 0; i < _spaceNodes.size(); i++)
	{
		SpaceNode* nodeA = _spaceNodes[i];
		SpaceNode* nodeB = bodyProxy->leaf;
		if (nodeA == nodeB)
			continue;
		BodyProxy* proxyA = nodeA->value;
		BodyProxy* proxyB = nodeB->value;
		_overlapPairs.insert(IOverlapPair(proxyA, proxyB));
	}
}
void IBroadphase::updateProxy(BBody* body)
{
	if (BodyProxy* bodyProxy = body_member(body)->bodyProxy)
	{
		BSpace space = body->space();
		const BVector delta = space.min() - bodyProxy->space.min();
		bool docollide = _spaceTree.update(bodyProxy->leaf, space, delta);
		bodyProxy->space = space;
		if (docollide)
		{
			for (int i = 0; i < _overlapPairs.size(); ++i)
			{
				IOverlapPair& pair = _overlapPairs.at(i);
				const BSpace& space0 = pair.proxy0->leaf->space;
				const BSpace& space1 = pair.proxy1->leaf->space;
				if (space0.intersect(space1))
					continue;
				_overlapPairs.remove(i--);
			}
			_spaceTree.collide(_spaceTree.root(), bodyProxy->leaf, _spacePairs);
			for (int i = 0; i < _spacePairs.size(); i++)
			{
				SpacePair& pair = _spacePairs[i];
				BodyProxy* proxyA = pair.nodeA->value;
				BodyProxy* proxyB = pair.nodeB->value;
				_overlapPairs.insert(IOverlapPair(proxyA, proxyB));
			}
		}
	}
}
void IBroadphase::removeProxy(BBody* body)
{
	if (BodyProxy* bodyProxy = body_member(body)->bodyProxy)
	{
		_spaceTree.remove(bodyProxy->leaf);
		for (int i = 0; i < _overlapPairs.size(); i++)
		{
			IOverlapPair& pair = _overlapPairs.at(i);
			if ((pair.proxy0 == bodyProxy) || (pair.proxy1 == bodyProxy))
			{
				_overlapPairs.remove(i--);
			}
		}
	}
}
void IBroadphase::clearProxy()
{
	_spaceTree.clear();
	_spaceNodes.clear();
	_spacePairs.clear();
	_overlapPairs.clear();
}

int IBroadphase::overlapPairCount() const
{
	return _overlapPairs.size();
}
IOverlapPair& IBroadphase::overlapPair(int index)
{
	return _overlapPairs.at(index);
}
